/**
 * Yarbu is a proof of concept of a JavaScript HTTP server.
 * Copyright (C) 2011 Antonio Hernandez Diaz <ahdiaz@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $Id: base.js 2 2011-01-08 06:03:19Z ahdiaz $
 */

function $A(a) {
	return Array.prototype.slice.call(a);
}

function dump(obj) {
	for (var o in obj) {
		print(o);
	}
}

function printf(/* string, value1, value2, ... */) {
	var values = $A(arguments);
	var string = values.shift();
	var c = 0;
	return string.replace(/%[sd]/g, function(match, position, string) {
		var value = values[c];
		switch (match) {
			case '%s':
				value = new String(value).valueOf();
				break;
			case '%d':
				value = new Number(value).valueOf();
				break;
		}
		c++;
		return value;
	});
}

function isObject(object) {
	object = isUndefined(object) ? null : object;
	return (
		object !== null &&
		typeof(object) == 'object' &&
		!isArray(object)
	);
}

function isString(object) {
	object = isUndefined(object) ? null : object;
	return typeof(object) == 'string';
}

function isNumber(object) {
	object = isUndefined(object) ? null : object;
	return typeof(object) == 'number';
}

function isArray(object) {
	object = isUndefined(object) ? null : object;
	return (
		object !== null &&
		typeof(object) == 'object' &&
		'splice' in object &&
		'join' in object
	);
}

function isNull(object) {
	return object === null;
}

function isUndefined(object) {
	return typeof(object) == 'undefined';
}

function isEmpty(object) {
	var empty = (
			object === null ||
			isUndefined(object) ||
			(isString(object) && object.length == 0)
		);
		return empty;
}

function isFunction(object) {
	object = isUndefined(object) ? null : object;
	return typeof(object) == 'function';
}

function isBoolean(object) {
	object = isUndefined(object) ? 0 : object;
	return typeof(object.valueOf()) == 'boolean';
}

function each(arr, callback) {
	if (!isFunction(callback)) return;
	for (var i=0, l=arr.length; i<l; i++) {
		callback(i, this[i]);
	}
}

function contains(value, arr) {
	var l = arr.length;
	while (--l >= 0) {
		if (this[l] === value) return true;
	}
	return false;
}

var ltrim = null;
var rtrim = null;
var trim = null;

(function() {

	// Characters to substitute:: TAB, SPACE, LINE FEED, CARRIAGE RETURN
	var trimChars = ['\u0009', '\u0020', '\u000A', '\u000D'];

	ltrim = function(str) {
		for (var i=0, l=str.length; i<l; i++) {
			if (contains(str.charAt(0), trimChars)) {
				str = str.substring(1);
			} else {
				break;
			}
		}
		return str;
	}

	rtrim = function(str) {
		for (var i=str.length-1; i>=0; i=str.length-1) {
			if (contains(str.charAt(str.length-1), trimChars)) {
				str = str.substring(0, str.length-1);
			} else {
				break;
			}
		}
		return str;
	}

	trim = function(str) {
		return str.ltrim().rtrim();
	}

})();

function capitalize(str) {
	return str.replace(/(^|\s)([a-z])/g, function(m, p1, p2) {
		return p1 + p2.toUpperCase();
	});
}

function rand(lower, upper) {
	lower = lower || 0;
	upper = upper || 1;
	var n = Math.floor((upper-(lower-1)) * Math.random()) + lower;
	return n;
}

function bind(/* scope, function [, arg1, ..., argN] */) {
	var args = $A(arguments);
	var scope = args.shift();
	var fn = args.shift();
	return function() {
		var params = $A(arguments);
		params = params.concat(args);
		return fn.apply(scope, params);
	}
}

function extend(base, iface) {
	for (var o in iface) {
		base[o] = iface[o];
	}
	return base;
}

function klass() {

	var ifaces = $A(arguments);
	var F = function() {
		if (typeof(this._init) == 'function') this._init.apply(this, arguments);
	};

	for (var i=0,l=ifaces.length; i<l; i++) {

		var iface = ifaces[i];

		if (iface._static || iface._private || iface._public) {
			if (iface._static) extend(F, iface._static.prototype || iface._static);
			//if (iface._private) extend(F.prototype, iface._private.prototype || iface._private);
			if (iface._public) extend(F.prototype, iface._public.prototype || iface._public);
		} else {
			extend(F.prototype, iface.prototype || iface);
		}
	}

	F.getClass = function() {
		return F;
	};

	return F;
}
